package com.central.scheduler.service.registry;

import com.central.scheduler.common.Constants;
import com.central.scheduler.common.enums.NodeType;
import com.central.scheduler.common.utils.HeartBeat;
import com.central.scheduler.dao.entity.Server;
import com.central.scheduler.common.utils.JSONUtils;

import java.util.*;

import static com.central.scheduler.common.Constants.*;

/**
 * @author Tindy
 * @date 2021/10/29
 * @describe
 */
public class RegistryClient  extends RegistryCenter {
    private static RegistryClient registryClient = new RegistryClient();

    private RegistryClient() {
        super.init();
    }
    /**
     * check dead server or not , if dead, stop self
     *
     * @param node node path
     * @param serverType master or worker prefix
     * @return true if not exists
     * @throws Exception errors
     */
    public boolean checkIsDeadServer(String node, String serverType) throws Exception {
        // ip_sequence_no
        String[] zNodesPath = node.split("\\/");
        String ipSeqNo = zNodesPath[zNodesPath.length - 1];
        String deadServerPath = getDeadZNodeParentPath() + SINGLE_SLASH + serverType + UNDERLINE + ipSeqNo;

        return !isExisted(node) || isExisted(deadServerPath);
    }
    public static RegistryClient getInstance() {
        return registryClient;
    }
    /**
     * @return get master start up lock path
     */
    public String getMasterStartUpLockPath() {
        return Constants.REGISTRY_SCHEDULER_LOCK_FAILOVER_STARTUP_MASTERS;
    }
    /**
     * @return get master failover lock path
     */
    public String getMasterFailoverLockPath() {
        return Constants.REGISTRY_SCHEDULER_LOCK_FAILOVER_MASTERS;
    }

    /**
     * @return get worker failover lock path
     */
    public String getWorkerFailoverLockPath() {
        return Constants.REGISTRY_SCHEDULER_LOCK_FAILOVER_WORKERS;
    }
    /**
     * get server list.
     *
     * @param nodeType zookeeper node type
     * @return server list
     */
    public List<Server> getServerList(NodeType nodeType) {
        Map<String, String> serverMaps = getServerMaps(nodeType);
        String parentPath = getNodeParentPath(nodeType);

        List<Server> serverList = new ArrayList<>();
        for (Map.Entry<String, String> entry : serverMaps.entrySet()) {
            HeartBeat heartBeat = HeartBeat.decodeHeartBeat(entry.getValue());
            if (heartBeat == null) {
                continue;
            }

            Server server = new Server();
            server.setResInfo(JSONUtils.toJsonString(heartBeat));
            server.setCreateTime(new Date(heartBeat.getStartupTime()));
            server.setLastHeartbeatTime(new Date(heartBeat.getReportTime()));
            server.setId(heartBeat.getProcessId());

            String key = entry.getKey();
            server.setZkDirectory(parentPath + "/" + key);
            // set host and port
            String[] hostAndPort = key.split(COLON);
            String[] hosts = hostAndPort[0].split(DIVISION_STRING);
            // fetch the last one
            server.setHost(hosts[hosts.length - 1]);
            server.setPort(Integer.parseInt(hostAndPort[1]));
            serverList.add(server);
        }
        return serverList;
    }


    /**
     * @return get master lock path
     */
    public String getMasterLockPath() {
        return Constants.REGISTRY_SCHEDULER_LOCK_MASTERS;
    }
    /**
     * get master nodes directly
     *
     * @return master nodes
     */
    public Set<String> getMasterNodesDirectly() {
        List<String> masters = getChildrenKeys(REGISTRY_SCHEDULER_MASTERS);
        return new HashSet<>(masters);
    }

}
